package com.sc.admin.core.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sc.admin.core.bo.CompanyBo;
import com.sc.admin.core.bo.DepartmentBo;
import com.sc.admin.core.bo.ProjectBo;
import com.sc.admin.core.bo.RoleBo;
import com.sc.admin.core.dao.*;
import com.sc.admin.core.service.SysOrganizationService;
import com.sc.admin.core.dao.*;
import com.sc.common.context.DefaultBusinessContext;
import com.sc.common.mapper.IBaseMapper;
import com.sc.common.dto.WebResponseDto;
import com.sc.common.entity.admin.account.SysAccount;
import com.sc.common.entity.admin.apptoken.SysAppToken;
import com.sc.common.entity.admin.company.SysCompany;
import com.sc.common.entity.admin.department.SysDepartment;
import com.sc.common.entity.admin.menu.SysMenu;
import com.sc.common.entity.admin.organization.SysOrganization;
import com.sc.common.entity.admin.organization.SysOrganizationSearch;
import com.sc.common.entity.admin.project.SysProject;
import com.sc.common.entity.admin.resource.SysResource;
import com.sc.common.entity.admin.role.SysRole;
import com.sc.common.entity.admin.role.resource.SysRoleResource;
import com.sc.common.entity.admin.user.SysUser;
import com.sc.common.enums.ApplicationEnum;
import com.sc.common.enums.DataDictionaryEnum;
import com.sc.common.enums.RedisKeyEnum;
import com.sc.common.exception.BusinessException;
import com.sc.common.lock.RedisDistributeLock;
import com.sc.common.service.BaseServiceImpl;
import com.sc.common.util.MyIdUtil;
import com.sc.common.util.PropertiesUtil;
import com.sc.common.util.RC4;
import com.sc.common.util.cache.DataDictionaryUtil;
import com.sc.common.util.cache.SpringRedisTools;
import com.sc.mq.producer.Producer4routingKey;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import java.util.*;

/**
 * Created by wust on 2019/6/3.
 */
@Service("sysOrganizationServiceImpl")
public class SysOrganizationServiceImpl extends BaseServiceImpl<SysOrganization> implements SysOrganizationService {
    @Autowired
    private SysOrganizationMapper sysOrganizationMapper;

    @Autowired
    private SysCompanyMapper sysCompanyMapper;

    @Autowired
    private SysProjectMapper sysProjectMapper;

    @Autowired
    private SysDepartmentMapper sysDepartmentMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleResourceMapper sysRoleResourceMapper;

    @Autowired
    private SysResourceMapper sysResourceMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private SysAccountMapper sysAccountMapper;

    @Autowired
    private SysAppTokenMapper sysAppTokenMapper;

    @Autowired
    private SpringRedisTools springRedisTools;

    @Autowired
    private RedisDistributeLock redisDistributeLock;

    @Autowired
    private Producer4routingKey producer4routingKey;

    @Autowired
    private Environment environment;

    @Autowired
    private SysDataSourceMapper sysDataSourceMapper;

    @Autowired
    private DepartmentBo departmentBo;

    @Autowired
    private CompanyBo companyBo;

    @Autowired
    private ProjectBo projectBo;

    @Autowired
    private RoleBo roleBo;


    @Override
    protected IBaseMapper getBaseMapper() {
        return sysOrganizationMapper;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto create(Object obj) {
        WebResponseDto responseDto = new WebResponseDto();
        return responseDto;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto update(Object obj) {
        WebResponseDto responseDto = new WebResponseDto();
        return responseDto;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto delete(Object obj) {
        WebResponseDto responseDto = new WebResponseDto();
        Long id = Convert.toLong(obj);
        SysOrganizationSearch sysOrganizationSearch = new SysOrganizationSearch();
        sysOrganizationSearch.setPid(id);
        List<SysOrganization> sysOrganizationLists = sysOrganizationMapper.select(sysOrganizationSearch);
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(sysOrganizationLists)){
            throw new BusinessException("您要删除的记录存在子节点，无法删除带有子节点的数据，请先删除所有子节点");
        }

        sysOrganizationMapper.deleteByPrimaryKey(id);
        return responseDto;
    }


    @Override
    public WebResponseDto buildLeftTree(SysOrganizationSearch search) {
        WebResponseDto responseDto = new WebResponseDto();
        JSONObject jsonObjectResult = new JSONObject();
        jsonObjectResult.put("leftTree",null);

        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        final JSONArray jsonArray = new JSONArray();

        List<SysOrganization> organizationAll = sysOrganizationMapper.selectAll();
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(organizationAll)){
            Map<Long,SysOrganization> result = groupById(organizationAll);
            if(ctx.isSuperAdmin() || ctx.isAdmin()){ // 平台管理员，构建所有组织
                JSONObject rootJSONObject = new JSONObject();
                rootJSONObject.put("id","-1");
                rootJSONObject.put("pId",null);
                rootJSONObject.put("name", messageSource.getMessage("common.systemName",null,ctx.getLocale()) + "(根节点)");
                rootJSONObject.put("shortName",messageSource.getMessage("common.systemName",null,ctx.getLocale()));
                rootJSONObject.put("type","");
                rootJSONObject.put("typeLabel","根节点");
                rootJSONObject.put("relationId",null);
                rootJSONObject.put("open",true);
                jsonArray.add(rootJSONObject);
                setRelationName(jsonArray,organizationAll);
            }else if(ctx.isStaff()){
                if(DataDictionaryEnum.USER_TYPE_AGENT.getStringValue().equals(ctx.getUser().getType())){ // 代理商，获取当前代理商的组织
                    /**
                     * 按照pid分组组织架构
                     */
                    Map<Long,List<SysOrganization>> groupByPidMap = groupByPid(organizationAll);


                    /**
                     * 根据当前登录用户获取其对应的组织架构id
                     */
                    SysOrganization sysOrganizationSearch = new SysOrganization();
                    sysOrganizationSearch.setType(DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());
                    sysOrganizationSearch.setRelationId(ctx.getAccountId());
                    List<SysOrganization> sysOrganizations = sysOrganizationMapper.select(sysOrganizationSearch);
                    if(!CollectionUtils.isEmpty(sysOrganizations)) {
                        /**
                         * 根据当前代理商用户向上递归获取代理商对应的组织架构id
                         */
                        JSONObject organizationId4agent = new JSONObject();
                        lookupOrganizationIdByType(result, sysOrganizations.get(0), DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue(), organizationId4agent);


                        /**
                         * 根据代理商组织架构id向下递归获取其所有组织架构
                         */
                        final List<SysOrganization> organizations4agent = new ArrayList<>(100);
                        SysOrganization organization4agent = sysOrganizationMapper.selectByPrimaryKey(organizationId4agent.getLong("id"));
                        organizations4agent.add(organization4agent);
                        lookupOrganizationByPid(groupByPidMap, organizationId4agent.getLong("id"), organizations4agent);


                        /**
                         * 设置组织架构节点名称
                         */
                        setRelationName(jsonArray, organizations4agent);
                    }
                }else if(DataDictionaryEnum.USER_TYPE_PARENT_COMPANY.getStringValue().equals(ctx.getUser().getType())){ // 总公司，获取当前总公司的组织
                    /**
                     * 按照pid分组组织架构
                     */
                    Map<Long,List<SysOrganization>> groupByPidMap = groupByPid(organizationAll);


                    /**
                     * 根据当前登录用户获取其对应的组织架构id
                     */
                    SysOrganization sysOrganizationSearch = new SysOrganization();
                    sysOrganizationSearch.setType(DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());
                    sysOrganizationSearch.setRelationId(ctx.getAccountId());
                    List<SysOrganization> sysOrganizations = sysOrganizationMapper.select(sysOrganizationSearch);
                    if(!CollectionUtils.isEmpty(sysOrganizations)) {
                        /**
                         * 根据当前总公司用户向上递归获取总公司对应的组织架构id
                         */
                        JSONObject organizationId4parentCompany = new JSONObject();
                        lookupOrganizationIdByType(result, sysOrganizations.get(0), DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue(), organizationId4parentCompany);


                        /**
                         * 根据总公司组织架构id向下递归获取其所有组织架构
                         */
                        final List<SysOrganization> organizations4parentCompany = new ArrayList<>(100);
                        SysOrganization organization4parentCompany = sysOrganizationMapper.selectByPrimaryKey(organizationId4parentCompany.getLong("id"));
                        organizations4parentCompany.add(organization4parentCompany);
                        lookupOrganizationByPid(groupByPidMap, organizationId4parentCompany.getLong("id"), organizations4parentCompany);


                        /**
                         * 设置组织架构节点名称
                         */
                        setRelationName(jsonArray, organizations4parentCompany);
                    }
                }else if(DataDictionaryEnum.USER_TYPE_BRANCH_COMPANY.getStringValue().equals(ctx.getUser().getType())){ // 分公司
                    /**
                     * 按照pid分组组织架构
                     */
                    Map<Long,List<SysOrganization>> groupByPidMap = groupByPid(organizationAll);


                    /**
                     * 根据当前登录用户获取其对应的组织架构id
                     */
                    SysOrganization sysOrganizationSearch = new SysOrganization();
                    sysOrganizationSearch.setType(DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());
                    sysOrganizationSearch.setRelationId(ctx.getAccountId());
                    List<SysOrganization> sysOrganizations = sysOrganizationMapper.select(sysOrganizationSearch);
                    if(!CollectionUtils.isEmpty(sysOrganizations)) {
                        /**
                         * 根据当前分公司用户向上递归获取分公司对应的组织架构id
                         */
                        JSONObject organizationId4branchCompany = new JSONObject();
                        lookupOrganizationIdByType(result, sysOrganizations.get(0), DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue(), organizationId4branchCompany);


                        /**
                         * 根据分公司组织架构id向下递归获取其所有组织架构
                         */
                        final List<SysOrganization> organizations4branchCompany = new ArrayList<>(100);
                        SysOrganization organization4branchCompany = sysOrganizationMapper.selectByPrimaryKey(organizationId4branchCompany.getLong("id"));
                        organizations4branchCompany.add(organization4branchCompany);
                        lookupOrganizationByPid(groupByPidMap, organizationId4branchCompany.getLong("id"), organizations4branchCompany);


                        /**
                         * 设置组织架构节点名称
                         */
                        setRelationName(jsonArray, organizations4branchCompany);
                    }
                }else if(DataDictionaryEnum.USER_TYPE_PROJECT.getStringValue().equals(ctx.getUser().getType())){ // 项目
                    /**
                     * 按照pid分组组织架构
                     */
                    Map<Long,List<SysOrganization>> groupByPidMap = groupByPid(organizationAll);


                    /**
                     * 根据当前登录用户获取其对应的组织架构id
                     */
                    SysOrganization sysOrganizationSearch = new SysOrganization();
                    sysOrganizationSearch.setType(DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());
                    sysOrganizationSearch.setRelationId(ctx.getAccountId());
                    List<SysOrganization> sysOrganizations = sysOrganizationMapper.select(sysOrganizationSearch);
                    if(!CollectionUtils.isEmpty(sysOrganizations)) {
                        /**
                         * 根据当用户向上递归获取项目对应的组织架构id
                         */
                        JSONObject organizationId4project = new JSONObject();
                        lookupOrganizationIdByType(result, sysOrganizations.get(0), DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue(), organizationId4project);


                        /**
                         * 根据组织架构id向下递归获取其所有组织架构
                         */
                        final List<SysOrganization> organizations4project = new ArrayList<>(100);
                        SysOrganization organization4project = sysOrganizationMapper.selectByPrimaryKey(organizationId4project.getLong("id"));
                        organizations4project.add(organization4project);
                        lookupOrganizationByPid(groupByPidMap, organizationId4project.getLong("id"), organizations4project);


                        /**
                         * 设置组织架构节点名称
                         */
                        setRelationName(jsonArray, organizations4project);
                    }
                }else if(DataDictionaryEnum.USER_TYPE_BUSINESS.getStringValue().equals(ctx.getUser().getType())){
                    /**
                     * 按照pid分组组织架构
                     */
                    Map<Long,List<SysOrganization>> groupByPidMap = groupByPid(organizationAll);


                    /**
                     * 根据当前登录用户获取其对应的组织架构id
                     */
                    SysOrganization sysOrganizationSearch = new SysOrganization();
                    sysOrganizationSearch.setType(DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());
                    sysOrganizationSearch.setRelationId(ctx.getAccountId());
                    List<SysOrganization> sysOrganizations = sysOrganizationMapper.select(sysOrganizationSearch);
                    if(!CollectionUtils.isEmpty(sysOrganizations)){
                        /**
                         * 根据当用户向上递归获取分公司对应的组织架构id
                         */
                        JSONObject organizationId4branchCompany = new JSONObject();
                        lookupOrganizationIdByType(result,sysOrganizations.get(0),DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue(),organizationId4branchCompany);


                        /**
                         * 根据司组织架构id向下递归获取其所有组织架构
                         */
                        final List<SysOrganization> organizations4branchCompany = new ArrayList<>(100);
                        SysOrganization organization4branchCompany = sysOrganizationMapper.selectByPrimaryKey(organizationId4branchCompany);
                        organizations4branchCompany.add(organization4branchCompany);
                        lookupOrganizationByPid(groupByPidMap,organizationId4branchCompany.getLong("id"),organizations4branchCompany);


                        /**
                         * 设置组织架构节点名称
                         */
                        setRelationName(jsonArray,organizations4branchCompany);
                    }
                }
            }
        }

        if(jsonArray.size() == 0){
            JSONObject rootJSONObject = new JSONObject();
            rootJSONObject.put("id","-1");
            rootJSONObject.put("pId",null);
            rootJSONObject.put("name",messageSource.getMessage("common.systemName",null,ctx.getLocale()));
            rootJSONObject.put("type","");
            rootJSONObject.put("typeLabel","根节点");
            rootJSONObject.put("relationId",null);
            jsonArray.add(rootJSONObject);
        }
        jsonObjectResult.put("leftTree",jsonArray.toJSONString());
        responseDto.setObj(jsonObjectResult);
        return responseDto;
    }



    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto setFunctionPermissions(JSONObject jsonObject) {
        WebResponseDto mm = new WebResponseDto();
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();
        Long organizationId = jsonObject.getLong("organizationId");

        Example example = new Example(SysRoleResource.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("organizationId",organizationId);
        sysRoleResourceMapper.deleteByExample(example);


        JSONArray  jsonArray = jsonObject.getJSONArray("sysRoleResources");
        List<SysRoleResource> list = new ArrayList<>();
        for (Object object : jsonArray) {
            JSONObject j = (JSONObject)object;
            SysRoleResource sysRoleResource = new SysRoleResource();
            sysRoleResource.setOrganizationId(organizationId);
            sysRoleResource.setResourceCode(j.getString("resourceCode"));
            sysRoleResource.setType(j.getString("type"));
            sysRoleResource.setCreaterId(ctx.getAccountId());
            sysRoleResource.setCreaterName(ctx.getAccountName());
            sysRoleResource.setCreateTime(new Date());
            sysRoleResource.setIsDeleted(0);
            list.add(sysRoleResource);

            // 将所勾选的菜单下面的所有私有白名单权限也自动授予角色
            if(ApplicationEnum.MENU_TYPE_M.getStringValue().equalsIgnoreCase(sysRoleResource.getType())){
                List<SysResource> anonList = sysResourceMapper.findAnonResourcesByMenuId(sysRoleResource.getResourceCode());
                if(!CollectionUtils.isEmpty(anonList)){
                    for(SysResource anonR : anonList){
                        SysRoleResource anon = new SysRoleResource();
                        anon.setOrganizationId(organizationId);
                        anon.setResourceCode(anonR.getCode());
                        anon.setType(ApplicationEnum.MENU_TYPE_R.getStringValue());
                        anon.setCreateTime(new Date());
                        anon.setIsDeleted(0);
                        list.add(anon);
                    }
                }
            }
        }

        sysRoleResourceMapper.insertList(list);
        return mm;
    }


    /**
     * 系统启动，初始化平台默认组织架构
     */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public void initDefaultOrganization() {
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        // ************************************* 初始化平台默认代理商 S
        SysCompany agentSearch = new SysCompany();
        agentSearch.setName(ApplicationEnum.DEFAULT_AGENT_NAME.getStringValue());
        agentSearch.setType("A101101");
        SysCompany agent = sysCompanyMapper.selectOne(agentSearch);
        if(agent != null){
            return;
        }

        agent = new SysCompany();
        agent.setId(MyIdUtil.getId());
        agent.setCode(companyBo.getCode());
        agent.setType("A101101");
        agent.setName(ApplicationEnum.DEFAULT_AGENT_NAME.getStringValue());
        agent.setAdminAccount("DLS10000");
        agent.setCreaterId(ctx.getAccountId());
        agent.setCreaterName(ctx.getAccountName());
        agent.setCreateTime(new Date());
        agent.setIsDeleted(0);

        SysOrganization organizationBindAgent = bind(agent.getId(),-1,DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue());
        createAgent(agent,organizationBindAgent.getId());
        // ************************************* 初始化平台默认代理商 E



        // ************************************* 初始化平台默认总公司 S
        SysCompany parentCompanySearch = new SysCompany();
        parentCompanySearch.setName(ApplicationEnum.DEFAULT_PARENT_COMPANY_NAME.getStringValue());
        parentCompanySearch.setType("A101104");
        SysCompany parentCompany = sysCompanyMapper.selectOne(parentCompanySearch);
        if(parentCompany != null){
            return;
        }

        parentCompany = new SysCompany();
        parentCompany.setId(MyIdUtil.getId());
        parentCompany.setCode(companyBo.getCode());
        parentCompany.setType("A101104");
        parentCompany.setName(ApplicationEnum.DEFAULT_PARENT_COMPANY_NAME.getStringValue());
        parentCompany.setAdminAccount("ZGS20000");
        parentCompany.setCreaterId(ctx.getAccountId());
        parentCompany.setCreaterName(ctx.getAccountName());
        parentCompany.setCreateTime(new Date());
        parentCompany.setIsDeleted(0);

        SysOrganization organizationBindParentCompany = bind(parentCompany.getId(),organizationBindAgent.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue());
        createParentCompany(parentCompany,organizationBindParentCompany.getId(),organizationBindParentCompany.getPid());
        // ************************************* 初始化平台默认总公司 E



        // ************************************* 初始化平台默认分公司，1260392325620830208L从datasource-company-map.propertis文件获取 S
        SysCompany branchCompany = sysCompanyMapper.selectByPrimaryKey(1260392325620830208L);
        if(branchCompany != null){
            return;
        }
        branchCompany = new SysCompany();
        branchCompany.setId(1260392325620830208L);
        branchCompany.setCode(companyBo.getCode());
        branchCompany.setType("A101107");
        branchCompany.setName(ApplicationEnum.DEFAULT_BRANCH_COMPANY_NAME.getStringValue());
        branchCompany.setAdminAccount("FGS30000");
        branchCompany.setCreaterId(ctx.getAccountId());
        branchCompany.setCreaterName(ctx.getAccountName());
        branchCompany.setCreateTime(new Date());
        branchCompany.setIsDeleted(0);

        SysOrganization organizationBindBranchCompany = bind(branchCompany.getId(),organizationBindParentCompany.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue());
        Map map = createBranchCompany(branchCompany,organizationBindBranchCompany.getId(),organizationBindBranchCompany.getPid());
        // ************************************* 初始化平台默认分公司 E



        // ************************************* 初始化平台默认项目 S
        SysProject projectSearch = new SysProject();
        projectSearch.setBranchCompanyId(branchCompany.getId());
        projectSearch.setName(ApplicationEnum.DEFAULT_PROJECT_NAME.getStringValue());
        SysProject project = sysProjectMapper.selectOne(projectSearch);
        if(project != null){
            return;
        }
        project = new SysProject();
        project.setId(MyIdUtil.getId());
        project.setCode(projectBo.getCode());
        project.setName(ApplicationEnum.DEFAULT_PROJECT_NAME.getStringValue());
        project.setAdminAccount("XM40000");
        project.setAgentId(agent.getId());
        project.setParentCompanyId(parentCompany.getId());
        project.setBranchCompanyId(branchCompany.getId());
        project.setCreaterId(ctx.getAccountId());
        project.setCreaterName(ctx.getAccountName());
        project.setCreateTime(new Date());
        project.setIsDeleted(0);

        SysOrganization organization4department1 = (SysOrganization)map.get("organization4department1");
        SysOrganization organizationBind = bind(project.getId(),organization4department1.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue());

        createProject(project,organizationBind.getId(),true);
        // ************************************* 初始化平台默认项目 E
    }



    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto createCompany(Map map) {
        WebResponseDto responseDto = new WebResponseDto();
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        JSONObject organizationJson = JSONObject.parseObject(map.get("organization").toString());
        JSONObject companyJson = JSONObject.parseObject(map.get("company").toString());
        String organizationType = organizationJson.getString("type");

        SysCompany companySearch = new SysCompany();
        companySearch.setName(companyJson.getString("name"));
        companySearch.setType(companyJson.getString("type"));
        SysCompany company = sysCompanyMapper.selectOne(companySearch);
        if(company != null){
            throw new BusinessException("在组织架构中已经存在该条记录，不允许重复添加");
        }

        company = new SysCompany();
        company.setId(MyIdUtil.getId());
        company.setCode(companyBo.getCode());
        company.setType(companyJson.getString("type"));
        company.setName(companyJson.getString("name"));
        company.setAdminAccount(companyJson.getString("adminAccount"));
        company.setCreaterId(ctx.getAccountId());
        company.setCreaterName(ctx.getAccountName());
        company.setCreateTime(new Date());
        company.setIsDeleted(0);


        SysOrganization organizationBind = new SysOrganization();

        if(DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue().equals(organizationType)){ // 代理商
            organizationBind = bind(company.getId(),organizationJson.getLong("pid"),organizationType);
            createAgent(company,organizationBind.getId());
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue().equals(organizationType)){ // 总公司
            organizationBind = bind(company.getId(),organizationJson.getLong("pid"),organizationType);
            createParentCompany(company,organizationBind.getId(),organizationBind.getPid());
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue().equals(organizationType)){ // 分公司
            final TreeSet<Long> treeSet = new TreeSet<>();
            Object obj = springRedisTools.getByKey(RedisKeyEnum.REDIS_KEY_COMPANY_ID_LIST.getStringValue());
            if(obj == null){ // 缓存没有分公司ID，则从配置文件获取
                Properties properties = PropertiesUtil.getDataSourceCompanyMapProperties();
                Set<String> names = properties.stringPropertyNames();
                for (String name : names) {
                    Long id = Long.parseLong(name);
                    treeSet.add(id);
                }
            }else{
                JSONArray jsonArray = JSONArray.parseArray(obj.toString());
                for (Object o : jsonArray) {
                    Long id = Long.parseLong(o.toString());
                    treeSet.add(id);
                }
            }

            for (Long aLong : treeSet) {
                SysCompany companyExists = sysCompanyMapper.selectByPrimaryKey(aLong);
                if(companyExists == null){
                    if(aLong != null && aLong.longValue() != 0){
                        try {
                            boolean lock = redisDistributeLock.lock(aLong+"");
                            if (lock) {
                                company.setId(aLong);
                                organizationBind = bind(company.getId(),organizationJson.getLong("pid"),organizationType);
                                createBranchCompany(company, organizationBind.getId(), organizationBind.getPid());
                                break;
                            }
                        }finally {
                            redisDistributeLock.unLock(aLong+"");
                        }
                    }
                }
            }
        }

        responseDto.setObj(organizationBind);
        return responseDto;
    }



    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto createProject(Map map) {
        WebResponseDto responseDto = new WebResponseDto();
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        JSONObject organizationJson = JSONObject.parseObject(map.get("organization").toString());
        JSONObject projectJson = JSONObject.parseObject(map.get("project").toString());


        // 找到上级代理商和上级总公司和分公司
        SysOrganization departmentOrganization = sysOrganizationMapper.selectByPrimaryKey(organizationJson.getLong("pid"));
        SysDepartment department = sysDepartmentMapper.selectByPrimaryKey(departmentOrganization.getRelationId());


        SysProject projectSearch = new SysProject();
        projectSearch.setBranchCompanyId(department.getBranchCompanyId());
        projectSearch.setName(projectJson.getString("name"));
        SysProject project = sysProjectMapper.selectOne(projectSearch);
        if(project != null){
            throw new BusinessException("该节点下面已经存相同名称的记录，不允许重复添加");
        }

        project = new SysProject();
        project.setId(MyIdUtil.getId());
        project.setCode(projectBo.getCode());
        project.setName(projectJson.getString("name"));
        project.setAdminAccount(projectJson.getString("adminAccount"));
        project.setAddr(projectJson.getString("addr"));
        project.setDescription(projectJson.getString("description"));
        project.setAgentId(department.getAgentId());
        project.setParentCompanyId(department.getParentCompanyId());
        project.setBranchCompanyId(department.getBranchCompanyId());
        project.setCreaterId(ctx.getAccountId());
        project.setCreaterName(ctx.getAccountName());
        project.setCreateTime(new Date());
        project.setIsDeleted(0);


        /**
         * 绑定项目到组织架构
         */
        SysOrganization organizationBind = bind(project.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue());

        createProject(project,organizationBind.getId(),false);

        responseDto.setObj(organizationBind);
        return responseDto;
    }


    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto createDepartment(Map map) {
        WebResponseDto responseDto = new WebResponseDto();
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        JSONObject organizationJson = JSONObject.parseObject(map.get("organization").toString());
        JSONObject departmentJson = JSONObject.parseObject(map.get("department").toString());

        SysOrganization organizationBind = null;
        // 找到上级代理商、上级总公司、分公司、项目
        SysOrganization parentOrganization = sysOrganizationMapper.selectByPrimaryKey(organizationJson.getLong("pid"));
        if(DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue().equals(parentOrganization.getType())){ // 如果上级是代理商，那么该部门属于代理商直接下属部门
            SysDepartment departmentSearch = new SysDepartment();
            departmentSearch.setAgentId(parentOrganization.getRelationId());
            departmentSearch.setName(departmentJson.getString("name"));
            SysDepartment department = sysDepartmentMapper.selectOne(departmentSearch);
            if(department != null){
                throw new BusinessException("该节点下已经存在该部门，不允许重复添加");
            }

            department = new SysDepartment();
            department.setId(MyIdUtil.getId());
            department.setCode(departmentBo.getCode());
            department.setName(departmentJson.getString("name"));
            department.setAgentId(parentOrganization.getRelationId());
            department.setCreaterId(ctx.getAccountId());
            department.setCreaterName(ctx.getAccountName());
            department.setCreateTime(new Date());
            department.setIsDeleted(0);
            sysDepartmentMapper.insert(department);

            organizationBind = bind(department.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue());
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue().equals(parentOrganization.getType())){// 如果上级是总公司，那么该部门属于总公司直接下属部门
            SysDepartment departmentSearch = new SysDepartment();
            departmentSearch.setParentCompanyId(parentOrganization.getRelationId());
            departmentSearch.setName(departmentJson.getString("name"));
            SysDepartment department = sysDepartmentMapper.selectOne(departmentSearch);
            if(department != null){
                throw new BusinessException("该节点下已经存在该部门，不允许重复添加");
            }

            SysOrganization agentOrganization = sysOrganizationMapper.selectByPrimaryKey(parentOrganization.getPid());
            department = new SysDepartment();
            department.setId(MyIdUtil.getId());
            department.setCode(departmentBo.getCode());
            department.setName(departmentJson.getString("name"));
            department.setAgentId(agentOrganization.getRelationId());
            department.setParentCompanyId(parentOrganization.getRelationId());
            department.setCreaterId(ctx.getAccountId());
            department.setCreaterName(ctx.getAccountName());
            department.setCreateTime(new Date());
            department.setIsDeleted(0);
            sysDepartmentMapper.insert(department);

            organizationBind = bind(department.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue());
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue().equals(parentOrganization.getType())){// 如果上级是分公司，那么该部门属于分公司直接下属部门
            SysDepartment departmentSearch = new SysDepartment();
            departmentSearch.setBranchCompanyId(parentOrganization.getRelationId());
            departmentSearch.setName(departmentJson.getString("name"));
            SysDepartment department = sysDepartmentMapper.selectOne(departmentSearch);
            if(department != null){
                throw new BusinessException("该节点下已经存在该部门，不允许重复添加");
            }

            SysOrganization parentCompanyOrganization = sysOrganizationMapper.selectByPrimaryKey(parentOrganization.getPid());
            SysOrganization agentOrganization = sysOrganizationMapper.selectByPrimaryKey(parentCompanyOrganization.getPid());

            department = new SysDepartment();
            department.setId(MyIdUtil.getId());
            department.setCode(departmentBo.getCode());
            department.setName(departmentJson.getString("name"));
            department.setAgentId(agentOrganization.getRelationId());
            department.setParentCompanyId(parentCompanyOrganization.getRelationId());
            department.setBranchCompanyId(parentOrganization.getRelationId());
            department.setCreaterId(ctx.getAccountId());
            department.setCreaterName(ctx.getAccountName());
            department.setCreateTime(new Date());
            department.setIsDeleted(0);
            sysDepartmentMapper.insert(department);

            organizationBind = bind(department.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue());
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue().equals(parentOrganization.getType())){// 如果上级是项目，那么该部门属于项目直接下属部门
            SysDepartment departmentSearch = new SysDepartment();
            departmentSearch.setProjectId(parentOrganization.getRelationId());
            departmentSearch.setName(departmentJson.getString("name"));
            SysDepartment department = sysDepartmentMapper.selectOne(departmentSearch);
            if(department != null){
                throw new BusinessException("该节点下已经存在该部门，不允许重复添加");
            }

            SysOrganization departmentCompanyOrganization = sysOrganizationMapper.selectByPrimaryKey(parentOrganization.getPid()); // 项目的上级是项目部门
            SysOrganization branchCompanyOrganization = sysOrganizationMapper.selectByPrimaryKey(departmentCompanyOrganization.getPid()); // 项目部门的上级是分公司
            SysOrganization parentCompanyOrganization = sysOrganizationMapper.selectByPrimaryKey(branchCompanyOrganization.getPid()); // 分公司的上级是总公司
            SysOrganization agentOrganization = sysOrganizationMapper.selectByPrimaryKey(parentCompanyOrganization.getPid()); // 总公司的上级是代理商

            department = new SysDepartment();
            department.setId(MyIdUtil.getId());
            department.setCode(departmentBo.getCode());
            department.setType(departmentJson.getString("type"));
            department.setDescription(departmentJson.getString("description"));
            department.setName(departmentJson.getString("name"));
            department.setAgentId(agentOrganization.getRelationId());
            department.setParentCompanyId(parentCompanyOrganization.getRelationId());
            department.setBranchCompanyId(branchCompanyOrganization.getRelationId());
            department.setProjectId(parentOrganization.getRelationId());
            department.setCreaterId(ctx.getAccountId());
            department.setCreaterName(ctx.getAccountName());
            department.setCreateTime(new Date());
            department.setIsDeleted(0);
            sysDepartmentMapper.insert(department);

            organizationBind = bind(department.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue());
        }

        responseDto.setObj(organizationBind);
        return responseDto;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto createRole(Map map) {
        WebResponseDto responseDto = new WebResponseDto();
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        JSONObject organizationJson = JSONObject.parseObject(map.get("organization").toString());
        JSONObject roleJson = JSONObject.parseObject(map.get("role").toString());



        // 找到上级代理商、上级总公司、分公司、项目、部门
        SysOrganization departmentOrganization = sysOrganizationMapper.selectByPrimaryKey(organizationJson.getLong("pid"));
        SysDepartment department = sysDepartmentMapper.selectByPrimaryKey(departmentOrganization.getRelationId());

        SysRole roleSearch = new SysRole();
        roleSearch.setAgentId(department.getAgentId());
        roleSearch.setParentCompanyId(department.getParentCompanyId());
        roleSearch.setBranchCompanyId(department.getBranchCompanyId());
        roleSearch.setProjectId(department.getProjectId());
        roleSearch.setName(roleJson.getString("name"));
        SysRole role = sysRoleMapper.selectOne(roleSearch);
        if(role != null){
            throw new BusinessException("该节点下已经存在该岗位，不允许重复添加");
        }

        role = new SysRole();
        role.setId(MyIdUtil.getId());
        role.setCode(roleBo.getCode());
        role.setDescription(roleJson.getString("description"));
        role.setName(roleJson.getString("name"));
        role.setStatus("A100201");
        role.setAgentId(department.getAgentId());
        role.setParentCompanyId(department.getParentCompanyId());
        role.setBranchCompanyId(department.getBranchCompanyId());
        role.setProjectId(department.getProjectId());
        role.setCreaterId(ctx.getAccountId());
        role.setCreaterName(ctx.getAccountName());
        role.setCreateTime(new Date());
        role.setIsDeleted(0);
        sysRoleMapper.insert(role);

        SysOrganization organizationBind = bind(role.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_ROLE.getStringValue());

        responseDto.setObj(organizationBind);
        return responseDto;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public WebResponseDto addUser(Map map) {
        WebResponseDto responseDto = new WebResponseDto();
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        JSONObject organizationJson = JSONObject.parseObject(map.get("organization").toString());


        // 找到上级岗位
        SysOrganization roleOrganization = sysOrganizationMapper.selectByPrimaryKey(organizationJson.getLong("pid"));
        SysRole role = sysRoleMapper.selectByPrimaryKey(roleOrganization.getRelationId());


        SysOrganization organizationSearch = new SysOrganization();
        organizationSearch.setPid(organizationJson.getLong("pid"));
        organizationSearch.setRelationId(organizationJson.getLong("relationId"));
        SysOrganization organization = sysOrganizationMapper.selectOne(organizationSearch);
        if(organization != null){
            throw new BusinessException("此节点下已经存在该员工，不需要重复添加");
        }


        SysUser user = sysUserMapper.selectByPrimaryKey(organizationJson.getLong("relationId"));
        if(user != null && user.getBranchCompanyId() != null){
            throw new BusinessException("系统发现此账号已经入职其他公司，系统暂时不支持同一个账号出现在不同的公司下面！");
        }
        user.setAgentId(role.getAgentId());
        user.setParentCompanyId(role.getParentCompanyId());
        user.setBranchCompanyId(role.getBranchCompanyId());
        user.setModifyId(ctx.getAccountId());
        user.setModifyName(ctx.getAccountName());
        user.setModifyTime(new Date());
        sysUserMapper.updateByPrimaryKeySelective(user);


        SysOrganization organizationBind = bind(user.getId(),organizationJson.getLong("pid"),DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());

        responseDto.setObj(organizationBind);
        return responseDto;
    }


    private void createAgent(SysCompany company, Long pid){
        sysCompanyMapper.insert(company);

        long departmentId = getDepartmentByName("A102701","运营管理部",company.getId(),null,null,null);
        SysOrganization organization4department = bind(departmentId,pid,DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue());


        long roleId = getRoleIdByName("运营管理员",company.getId(),null,null,null);
        SysOrganization organization4role = bind(roleId,organization4department.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_ROLE.getStringValue());


        long userId = registerAccount(company.getId(),null,null,null,company.getAdminAccount(),company.getName(),"A100403");
        bind(userId,organization4role.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());

        initPermissions(organization4role.getId(),roleId,DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue());
    }

    private void createParentCompany(SysCompany company,Long id, Long pid){
        sysCompanyMapper.insert(company);

        // 找到上级代理商
        SysOrganization agentOrganization = sysOrganizationMapper.selectByPrimaryKey(pid);

        long departmentId = getDepartmentByName("A102701","运营管理部",agentOrganization.getRelationId(),company.getId(),null,null);
        SysOrganization organization4department = bind(departmentId,id,"A101111");

        long roleId = getRoleIdByName("运营管理员",agentOrganization.getRelationId(),company.getId(),null,null);
        SysOrganization organization4role = bind(roleId,organization4department.getId(),"A101113");

        long userId = registerAccount(agentOrganization.getRelationId(),company.getId(),null,null,company.getAdminAccount(),company.getName(),"A100406");
        bind(userId,organization4role.getId(),"A101115");

        initPermissions(organization4role.getId(),roleId,DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue());
    }


    private Map createBranchCompany(SysCompany company,Long id, Long pid){
        Map map = new HashMap();

        sysCompanyMapper.insert(company);

        // 找到上级代理商和上级总公司
        SysOrganization parentCompanyOrganization = sysOrganizationMapper.selectByPrimaryKey(pid);
        SysOrganization agentOrganization = sysOrganizationMapper.selectByPrimaryKey(parentCompanyOrganization.getPid());

        long departmentId = getDepartmentByName("A102701","运营管理部",agentOrganization.getRelationId(),parentCompanyOrganization.getRelationId(),company.getId(),null);
        SysOrganization organization4department = bind(departmentId,id,"A101111");


        long departmentId1 = getDepartmentByName("A102703","项目管理部",agentOrganization.getRelationId(),parentCompanyOrganization.getRelationId(),company.getId(),null);
        SysOrganization organization4department1 = bind(departmentId1,id,"A101111");


        long roleId = getRoleIdByName("运营管理员",agentOrganization.getRelationId(),parentCompanyOrganization.getRelationId(),company.getId(),null);
        SysOrganization organization4role = bind(roleId,organization4department.getId(),"A101113");


        long userId = registerAccount(agentOrganization.getRelationId(),parentCompanyOrganization.getRelationId(),company.getId(),null,company.getAdminAccount(),company.getName(),"A100409");
        SysOrganization organization4user = bind(userId,organization4role.getId(),"A101115");


        initPermissions(organization4role.getId(),roleId,DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue());

        map.put("organization4department",organization4department);
        map.put("organization4department1",organization4department1);
        map.put("organization4role",organization4role);
        map.put("organization4user",organization4user);
        return map;
    }





    private void createProject(SysProject project, Long id, boolean isDefaultDb) {
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        sysProjectMapper.insert(project);

        /**
         * 绑定部门到组织架构
         */
        long departmentId = getDepartmentByName("A102701","运营管理部",project.getAgentId(),project.getParentCompanyId(),project.getBranchCompanyId(),project.getId());
        SysOrganization organization4department = bind(departmentId,id,DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue());


        /**
         * 绑定岗位到组织架构
         */
        long roleId = getRoleIdByName("运营管理员",project.getAgentId(),project.getParentCompanyId(),project.getBranchCompanyId(),project.getId());
        SysOrganization organization4role = bind(roleId,organization4department.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_ROLE.getStringValue());



        /**
         * 绑定用户到组织架构
         */
        long userId = registerAccount(project.getAgentId(),project.getParentCompanyId(),project.getBranchCompanyId(),project.getId(),project.getAdminAccount(),project.getName(),"A100410");
        bind(userId,organization4role.getId(),DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue());


        initPermissions(organization4role.getId(),roleId,DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue());

        /**
         * 为项目初始化接口访问秘钥
         */
        SysAppToken appToken = new SysAppToken();
        appToken.setId(MyIdUtil.getId());
        appToken.setAppId(UUID.randomUUID().toString().replaceAll("-","").toUpperCase());
        appToken.setSignSecretKey(UUID.randomUUID().toString().replaceAll("-","").toUpperCase());
        appToken.setStatus("A101202");
        appToken.setSignDuration((long)(2 * 60 * 1000));
        appToken.setApplicant(project.getName());
        appToken.setDescription("项目["+project.getName()+"]的接口调用钥匙");
        appToken.setAppExpireTime(DateTime.now().plusYears(10).toDate()); // 默认有效期十年
        appToken.setAgentId(project.getAgentId());
        appToken.setParentCompanyId(project.getParentCompanyId());
        appToken.setBranchCompanyId(project.getBranchCompanyId());
        appToken.setProjectId(project.getId());
        appToken.setCreaterId(ctx.getAccountId());
        appToken.setCreaterName(ctx.getAccountName());
        appToken.setCreateTime(new Date());
        appToken.setIsDeleted(0);
        sysAppTokenMapper.insert(appToken);
    }

    private Long getDepartmentByName(String type,String name,Long agentId,Long parentCompanyId,Long branchCompanyId,Long projectId){
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();
        SysDepartment departmentSearch = new SysDepartment();
        departmentSearch.setAgentId(agentId);
        departmentSearch.setParentCompanyId(parentCompanyId);
        departmentSearch.setBranchCompanyId(branchCompanyId);
        departmentSearch.setProjectId(projectId);
        departmentSearch.setName(name);
        departmentSearch.setType(type);
        SysDepartment department = sysDepartmentMapper.selectOne(departmentSearch);
        if(department == null){
            department = new SysDepartment();
            department.setId(MyIdUtil.getId());
            department.setName(departmentSearch.getName());
            department.setCode(departmentBo.getCode());
            department.setType(type);
            department.setAgentId(agentId);
            department.setParentCompanyId(parentCompanyId);
            department.setBranchCompanyId(branchCompanyId);
            department.setProjectId(projectId);
            department.setCreaterId(ctx.getAccountId());
            department.setCreaterName(ctx.getAccountName());
            department.setCreateTime(new Date());
            department.setIsDeleted(0);
            sysDepartmentMapper.insert(department);
        }
        return department.getId();
    }

    private Long getRoleIdByName(String name,Long agentId,Long parentCompanyId,Long branchCompanyId,Long projectId){
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();
        SysRole roleSearch = new SysRole();
        roleSearch.setAgentId(agentId);
        roleSearch.setParentCompanyId(parentCompanyId);
        roleSearch.setBranchCompanyId(branchCompanyId);
        roleSearch.setProjectId(projectId);
        roleSearch.setName(name);
        SysRole role = sysRoleMapper.selectOne(roleSearch);
        if(role == null){
            role = new SysRole();
            role.setId(MyIdUtil.getId());
            role.setName(roleSearch.getName());
            role.setCode(roleBo.getCode());
            role.setStatus("A100201");
            role.setAgentId(agentId);
            role.setParentCompanyId(parentCompanyId);
            role.setBranchCompanyId(branchCompanyId);
            role.setProjectId(projectId);
            role.setCreaterId(ctx.getAccountId());
            role.setCreaterName(ctx.getAccountName());
            role.setCreateTime(new Date());
            role.setIsDeleted(0);
            sysRoleMapper.insert(role);
        }
        return role.getId();
    }

    private long registerAccount(Long agentId,Long parentCompanyId,Long branchCompanyId,Long projectId,String loginName,String name,String type){
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();

        SysUser sysUserSearch = new SysUser();
        sysUserSearch.setLoginName(loginName);
        SysUser user = sysUserMapper.selectOne(sysUserSearch);
        if(user != null){
        }else{
            user = new SysUser();
            user.setId(MyIdUtil.getId());
            user.setLoginName(loginName);
            user.setRealName(name);
            user.setType(type);
            user.setStatus("A102901");
            user.setAgentId(agentId);
            user.setParentCompanyId(parentCompanyId);
            user.setBranchCompanyId(branchCompanyId);
            user.setCreaterId(ctx.getAccountId());
            user.setCreaterName(ctx.getAccountName());
            user.setCreateTime(new Date());
            user.setIsDeleted(0);
            sysUserMapper.insert(user);


            String passwordRC4 = RC4.encry_RC4_string(SecureUtil.md5("123456").toUpperCase(), ApplicationEnum.LOGIN_RC4_KEY.getStringValue());
            SysAccount account = new SysAccount();
            account.setId(user.getId());
            account.setAccountCode(user.getLoginName());
            account.setAccountName(user.getRealName());
            account.setType("A101703"); // 员工
            account.setPassword(passwordRC4);
            account.setCreaterId(ctx.getAccountId());
            account.setCreaterName(ctx.getAccountName());
            account.setCreateTime(new Date());
            account.setIsDeleted(0);
            this.sysAccountMapper.insert(account);
        }
        return user.getId();
    }

    private SysOrganization bind(long relationId,long pid,String type){
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();
        SysOrganization organization = new SysOrganization();
        organization.setId(MyIdUtil.getId());
        organization.setType(type);
        organization.setRelationId(relationId);
        organization.setPid(pid);
        organization.setCreaterId(ctx.getAccountId());
        organization.setCreaterName(ctx.getAccountName());
        organization.setCreateTime(new Date());
        organization.setIsDeleted(0);
        sysOrganizationMapper.insert(organization);
        return organization;
    }



    /**
     * 为角色初始化权限
     * @param organizationId 组织id
     * @param roleId 角色id
     * @param grandfatherType 角色的爷爷类型：项目、分公司、总公司、代理商
     * @return
     */
    private void initPermissions(Long organizationId, Long roleId, String grandfatherType){
        Locale locale = Locale.getDefault(); // 对Locale类实例化定义
        if(DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue().equals(grandfatherType)){ // 选中角色的爷爷组织类型：项目
            List<SysRoleResource> roleResources = new ArrayList<>();

            SysMenu menuSearch = new SysMenu();
            menuSearch.setLan(locale.toString());
            menuSearch.setUserType(DataDictionaryEnum.USER_TYPE_PROJECT.getStringValue());
            List<SysMenu> menus = sysMenuMapper.select(menuSearch);
            if(CollectionUtil.isNotEmpty(menus)){
                for (SysMenu menu : menus) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_M.getStringValue());
                    roleResource.setResourceCode(menu.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            SysResource resourceSearch = new SysResource();
            resourceSearch.setUserType(DataDictionaryEnum.USER_TYPE_PROJECT.getStringValue());
            resourceSearch.setLan(locale.toString());
            List<SysResource> resources = sysResourceMapper.select(resourceSearch);
            if(CollectionUtil.isNotEmpty(resources)){
                for (SysResource resource : resources) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_R.getStringValue());
                    roleResource.setResourceCode(resource.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            if(CollectionUtil.isNotEmpty(roleResources)){
                sysRoleResourceMapper.insertList(roleResources);
            }
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue().equals(grandfatherType)){ // 选中角色的爷爷组织类型：分公司，找分公司菜单资源
            List<SysRoleResource> roleResources = new ArrayList<>();

            SysMenu menuSearch = new SysMenu();
            menuSearch.setUserType(DataDictionaryEnum.USER_TYPE_BRANCH_COMPANY.getStringValue());
            menuSearch.setLan(locale.toString());
            List<SysMenu> menus = sysMenuMapper.select(menuSearch);
            if(CollectionUtil.isNotEmpty(menus)){
                for (SysMenu menu : menus) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_M.getStringValue());
                    roleResource.setResourceCode(menu.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            SysResource resourceSearch = new SysResource();
            resourceSearch.setUserType(DataDictionaryEnum.USER_TYPE_BRANCH_COMPANY.getStringValue());
            resourceSearch.setLan(locale.toString());
            List<SysResource> resources = sysResourceMapper.select(resourceSearch);
            if(CollectionUtil.isNotEmpty(resources)){
                for (SysResource resource : resources) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_R.getStringValue());
                    roleResource.setResourceCode(resource.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            if(CollectionUtil.isNotEmpty(roleResources)){
                sysRoleResourceMapper.insertList(roleResources);
            }
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue().equals(grandfatherType)){ // 选中角色的爷爷组织类型：总公司，找总公司菜单资源
            List<SysRoleResource> roleResources = new ArrayList<>();

            SysMenu menuSearch = new SysMenu();
            menuSearch.setUserType(DataDictionaryEnum.USER_TYPE_PARENT_COMPANY.getStringValue());
            menuSearch.setLan(locale.toString());
            List<SysMenu> menus = sysMenuMapper.select(menuSearch);
            if(CollectionUtil.isNotEmpty(menus)){
                for (SysMenu menu : menus) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_M.getStringValue());
                    roleResource.setResourceCode(menu.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            SysResource resourceSearch = new SysResource();
            resourceSearch.setUserType(DataDictionaryEnum.USER_TYPE_PARENT_COMPANY.getStringValue());
            resourceSearch.setLan(locale.toString());
            List<SysResource> resources = sysResourceMapper.select(resourceSearch);
            if(CollectionUtil.isNotEmpty(resources)){
                for (SysResource resource : resources) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_R.getStringValue());
                    roleResource.setResourceCode(resource.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            if(CollectionUtil.isNotEmpty(roleResources)){
                sysRoleResourceMapper.insertList(roleResources);
            }
        }else if(DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue().equals(grandfatherType)){ // 选中角色的爷爷组织类型：代理商，找代理商菜单资源
            List<SysRoleResource> roleResources = new ArrayList<>();

            SysMenu menuSearch = new SysMenu();
            menuSearch.setUserType(DataDictionaryEnum.USER_TYPE_AGENT.getStringValue());
            menuSearch.setLan(locale.toString());
            List<SysMenu> menus = sysMenuMapper.select(menuSearch);
            if(CollectionUtil.isNotEmpty(menus)){
                for (SysMenu menu : menus) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_M.getStringValue());
                    roleResource.setResourceCode(menu.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            SysResource resourceSearch = new SysResource();
            resourceSearch.setUserType(DataDictionaryEnum.USER_TYPE_AGENT.getStringValue());
            resourceSearch.setLan(locale.toString());
            List<SysResource> resources = sysResourceMapper.select(resourceSearch);
            if(CollectionUtil.isNotEmpty(resources)){
                for (SysResource resource : resources) {
                    SysRoleResource roleResource = new SysRoleResource();
                    roleResource.setType(ApplicationEnum.MENU_TYPE_R.getStringValue());
                    roleResource.setResourceCode(resource.getCode());
                    roleResource.setOrganizationId(organizationId);
                    roleResource.setRoleId(roleId);
                    roleResource.setCreateTime(new Date());
                    roleResource.setIsDeleted(0);
                    roleResources.add(roleResource);
                }
            }

            if(CollectionUtil.isNotEmpty(roleResources)){
                sysRoleResourceMapper.insertList(roleResources);
            }
        }
    }


    /**
     * 设置关系名称到组织架构
     * @param jsonArray            返回最终的组织架构树
     * @param sysOrganizationLists 需要获取关系名称的组织架构树
     */
    private void setRelationName(final JSONArray jsonArray,final List<SysOrganization> sysOrganizationLists){
        DefaultBusinessContext ctx = DefaultBusinessContext.getContext();
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(sysOrganizationLists)){
            for (SysOrganization sysOrganizationList : sysOrganizationLists) {
                JSONObject jsonObject = new JSONObject();

                String type = sysOrganizationList.getType();
                Long relationId = sysOrganizationList.getRelationId();
                String name = "";
                Long pid = sysOrganizationList.getPid();

                if(DataDictionaryEnum.ORGANIZATION_TYPE_AGENT.getStringValue().equalsIgnoreCase(type)){
                    SysCompany sysCompany = sysCompanyMapper.selectByPrimaryKey(relationId);
                    if(sysCompany != null){
                        name = sysCompany.getName();
                        pid = pid == null ? -1 : pid;
                    }
                }else if(DataDictionaryEnum.ORGANIZATION_TYPE_PARENT_COMPANY.getStringValue().equalsIgnoreCase(type)){
                    SysCompany sysCompany = sysCompanyMapper.selectByPrimaryKey(relationId);
                    if(sysCompany != null){
                        name = sysCompany.getName();
                    }
                }else if(DataDictionaryEnum.ORGANIZATION_TYPE_BRANCH_COMPANY.getStringValue().equalsIgnoreCase(type)){
                    SysCompany sysCompany = sysCompanyMapper.selectByPrimaryKey(relationId);
                    if(sysCompany != null){
                        name = sysCompany.getName();
                    }
                }else if(DataDictionaryEnum.ORGANIZATION_TYPE_PROJECT.getStringValue().equalsIgnoreCase(type)){
                    SysProject sysProject = sysProjectMapper.selectByPrimaryKey(relationId);
                    if(sysProject != null){
                        name = sysProject.getName();
                    }
                }else if(DataDictionaryEnum.ORGANIZATION_TYPE_DEPARTMENT.getStringValue().equalsIgnoreCase(type)){
                    SysDepartment sysDepartment = sysDepartmentMapper.selectByPrimaryKey(relationId);
                    if(sysDepartment != null){
                        name = sysDepartment.getName();
                    }
                }else if(DataDictionaryEnum.ORGANIZATION_TYPE_ROLE.getStringValue().equalsIgnoreCase(type)){
                    SysRole sysRole = sysRoleMapper.selectByPrimaryKey(relationId);
                    if(sysRole != null){
                        name = sysRole.getName();
                    }
                }else if(DataDictionaryEnum.ORGANIZATION_TYPE_USER.getStringValue().equalsIgnoreCase(type)){
                    SysUser sysUser = sysUserMapper.selectByPrimaryKey(relationId);
                    if(sysUser != null){
                        name = sysUser.getRealName() + "(" + sysUser.getLoginName() + ")";
                    }
                }

                jsonObject.put("id",sysOrganizationList.getId());
                jsonObject.put("pId",pid);
                jsonObject.put("name",name + "(" + DataDictionaryUtil.getLookupNameByCode(ctx.getLocale().toString(),type) + ")");
                jsonObject.put("shortName",name);
                jsonObject.put("type",type);
                jsonObject.put("typeLabel", DataDictionaryUtil.getLookupNameByCode(ctx.getLocale().toString(),type));
                jsonObject.put("relationId",relationId);
                jsonObject.put("open",name);
                jsonArray.add(jsonObject);
            }
        }
    }

    private Map<Long,SysOrganization> groupById(final List<SysOrganization> sysOrganizationLists){
        Map<Long,SysOrganization> result = new HashMap<>(sysOrganizationLists.size());
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(sysOrganizationLists)){
            for (SysOrganization sysOrganizationList : sysOrganizationLists) {
                result.put(sysOrganizationList.getId(),sysOrganizationList);
            }
        }
        return result;
    }

    private Map<Long,List<SysOrganization>> groupByPid(final List<SysOrganization> sysOrganizationLists){
        Map<Long,List<SysOrganization>> result = new HashMap<>(sysOrganizationLists.size());
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(sysOrganizationLists)){
            for (SysOrganization sysOrganizationList : sysOrganizationLists) {
                Long pid = sysOrganizationList.getPid();
                if(result.containsKey(pid)){
                    List<SysOrganization> list = result.get(pid);
                    list.add(sysOrganizationList);
                }else{
                    List<SysOrganization> list = new ArrayList<>();
                    list.add(sysOrganizationList);
                    result.put(pid,list);
                }
            }
        }
        return result;
    }


    /**
     * 向上递归，获取指定类型的组织架构id
     * @param map
     * @param current
     * @param type
     * @return
     */
    private void lookupOrganizationIdByType(Map<Long,SysOrganization> map,SysOrganization current,String type,JSONObject result){
        if(type.equals(current.getType())){
            result.put("id",current.getId());
            return;
        }

        if(map.containsKey(current.getPid())){
            SysOrganization c = map.get(current.getPid());
            lookupOrganizationIdByType(map,c,type,result);
        }
    }


    private void lookupOrganizationByPid(Map<Long,List<SysOrganization>> map,Long currentId,final List<SysOrganization> sysOrganizationLists){
        if(map.containsKey(currentId)){
            List<SysOrganization> children = map.get(currentId);
            if(org.apache.commons.collections.CollectionUtils.isNotEmpty(children)){
                for (SysOrganization child : children) {
                    sysOrganizationLists.add(child);
                    lookupOrganizationByPid(map,child.getId(),sysOrganizationLists);
                }
            }
        }
    }
}
